home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Basic Toolbox
/
Visual Basic Toolbox (P.I.E.)(1996).ISO
/
printing
/
vbprintn
/
vbprint.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-09
|
48KB
|
1,409 lines
/*************************************************************************
Print Engine for Visual Basic
Printing utilities for hardcopy output
Written by Barry Nolte
06-28-92 File Created
11-12-92 Added Graphics Functions
01-17-93 General Cleanup of Sources
02-03-93 Simple Bug Fixes
*************************************************************************/
// COPYRIGHT:
//
// (C) Copyright Microsoft Corp. 1993. All rights reserved.
//
// You have a royalty-free right to use, modify, reproduce and
// distribute the Sample Files (and/or any modified version) in
// any way you find useful, provided that you agree that
// Microsoft has no warranty obligations or liability for any
// Sample Application Files which are modified.
//
#include <windows.h>
#include <drivinit.h>
#include <commdlg.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include "vbprint.h"
// DLL Version Numbers
#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#define BORDER_WIDTH 2 // Default border in points
/*************************************************************************
GLOBAL VARIABLES
*************************************************************************/
static HANDLE hInst; // Handle to calling app
static HWND hWndApp; // Handle ot calling apps main window
static PRINTDLG ppPrinter; // Structure of printer properties
// Misc Procs
static FARPROC lpfnPrintDlgProc; // Printing dialog proc
static FARPROC lpfnAbortProc; // Printing about proc
static BOOL fAbort;
static struct tagPrinterInfo // Information on printer needed to place objects correctly
{
POINT ptPageSize; // Size of the page
RECT rcUnprintable; // Unprintable regions of the printer
RECT rcMargins; // Margins that are set in the Page Layout Function
POINT ptResolution; // Printer Resolution in device DPI
} PrinterInfo;
static struct tagPageInfo // Information on where I'm printing on the page
{
POINT ptCurrentPos; // Current Print Position
DWORD dwCurLineWidth; // Current Line Width, good for multiple calls to ParagraphText
int nTabStop; // Current Tab Stop value
BOOL bPageDirty; // Is the page dirty?
} PageInfo;
static struct tagParagraphInfo // Information on paragraph attributes
{
HFONT hFont; // Handle to paragraphs default font
HFONT hOldFont; // Handle to previous font
TEXTMETRIC tm; // Text metric struct that has info on the font
DWORD dwWidth; // Width of column to print into
int nStyle; // Border and Font Attributes
WORD wBorderWidth; // Border Width in device units (HIBYTE = Horizontal, LOBYTE = Vertical)
int nWidth[LAST_CHAR - FIRST_CHAR + 1]; // Widths of all the fonts characters
int nSpaceBefore; // Space before Paragraph in Points
int nSpaceAfter; // Space After Paragraph in Points
int nLeftIndent; // Paragraph Left Indent size, good for check box justification
} ParagraphInfo;
static struct tagColumnInfo // Information on printing columns
{
HFONT hFont; // Handle to paragraphs default font
HFONT hOldFont; // Handle to previous font
TEXTMETRIC tm; // Text Metric struct that has info on the font
WORD wBorderWidth; // Border Width in device units (HIBYTE = Horizontal, LOBYTE = Vertical)
int nNumColumns; // Number of vertical Columns
int nCellHeight; // Height of Cells
int rgColumnWidths[MAX_COLUMNS]; // Widths of Columns
int nWidth[LAST_CHAR - FIRST_CHAR + 1]; // Widths of all the fonts characters
int nStyle; // Border and Font attributes
} ColumnInfo;
/*************************************************************************
PROTOTYPES
*************************************************************************/
int FAR PASCAL PrinterSetup(HWND hWnd);
int FAR PASCAL InitializePrinter(HWND hWnd);
int FAR PASCAL PageLayoutSetup(int nTop, int nRight, int nBottom, int nLeft);
BOOL DoCommDlgError(HWND hWnd, DWORD dError);
int FAR PASCAL DonePrinting(void);
int FAR PASCAL StartParagraph(LPSTR szFontName, int nFontSize, int nStyle);
int FAR PASCAL FinishParagraph(void);
int FAR PASCAL PrintHeadline(LPSTR szHeadLine, LPSTR szFontName, int nFontSize, int nStyle);
int FAR PASCAL ParagraphText(LPSTR szText);
int FAR PASCAL EjectPage (void);
int TextOutAtCurPos(LPSTR szText);
int GetColumnOffset(int nColumn);
int CellDrawText(HDC hDC, LPSTR szText, LPRECT rc);
BOOL GetUnprintableRegion(HDC hDCPrn);
BOOL GetPrinterResolution(HDC hDCPrn);
BOOL FAR PASCAL PrnAbortProc(HDC hDCPrn, short nCode);
BOOL FAR PASCAL PrintDlgProc(HWND hDlg, WORD message, WORD wParam, LONG lParam);
int FAR PASCAL PrintDLLVersion(VOID);
BOOL FAR PASCAL SetParagraphSpacing(int nSpaceBefore, int nSpaceAfter);
BOOL FAR PASCAL SetBorderWidth(int nWidth);
int FAR PASCAL SetUpColumns(int nNumColumns, LPINT nC, LPSTR szFontName, int nFontSize, int nStyle);
int FAR PASCAL PrintColumnText(LPSTR szText);
int FAR PASCAL EndColumnPrinting(VOID);
int FAR PASCAL PrintColumnHeaders(LPSTR szHeader, int nNumColumns, LPINT nC, LPSTR szFontName, int nFontSize, int nStyle);
HDC GetPrinterDC(void);
BOOL FAR PASCAL KillJob(void);
BOOL FAR PASCAL PrinterName(LPSTR szPrinterName);
BOOL FAR PASCAL PrinterPort(LPSTR szPortName);
BOOL FAR PASCAL IsPageDirty(void);
int FAR PASCAL PagePosY(void);
int FAR PASCAL PagePosX(void);
int FAR PASCAL PageSizeY(void);
int FAR PASCAL PageSizeX(void);
BOOL FAR PASCAL MoveYPos(int nY);
int FDrawLine(HDC hDC, int nStartX, int nStartY, int nEndX, int nEndY);
int FDrawRectangle(HDC hDC, int nStartX, int nStartY, int nEndX, int nEndY);
int FDrawRndRectangle(HDC hDC, int nStartX, int nStartY, int nEndX, int nEndY, int nElpX, int nElpY);
int FDrawEllipse(HDC hDC, int nStartX, int nStartY, int nEndX, int nEndY);
BOOL FAR PASCAL DrawLine(int nX1, int nY1, int nX2, int nY2);
BOOL FAR PASCAL DrawRectangle(int nX1, int nY1, int nX2, int nY2);
BOOL FAR PASCAL DrawRndRectangle(int nX1, int nY1, int nX2, int nY2, int nX3, int nY3);
BOOL FAR PASCAL DrawEllipse(int nX1, int nY1, int nX2, int nY2);
/*************************************************************************
DLL initialization, called once when loaded
*************************************************************************/
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg, WORD wHeapSize, LPSTR lpszCmdLine)
{
hInst = hInstance; // Save this for later, we may need it
/* Set all structure members to zero. */
_fmemset(&ppPrinter, 0, sizeof(PRINTDLG));
return TRUE;
}
/*************************************************************************
Initialize Printer Driver and set defaults
*************************************************************************/
int FAR PASCAL InitializePrinter(HWND hWnd)
{
char szQueueName[80]={""};
hWndApp = hWnd; // Save the calling apps window handle so we can put up dialogs
fAbort = FALSE;
PageInfo.bPageDirty = FALSE;
ppPrinter.hDC = GetPrinterDC();
if (ppPrinter.hDC)
{
// Do stuff for AbortProc and Printing Dialog
lpfnAbortProc = MakeProcInstance(PrnAbortProc, hInst);
Escape(ppPrinter.hDC, SETABORTPROC, NULL, (LPSTR)(long)lpfnAbortProc, (LPSTR)NULL);
GetUnprintableRegion(ppPrinter.hDC);
GetPrinterResolution(ppPrinter.hDC);
LoadString(hInst, IDS_QUEUE_NAME, (LPSTR)szQueueName, 80);
Escape(ppPrinter.hDC, STARTDOC,lstrlen((LPSTR)szQueueName) ,(LPSTR)szQueueName, NULL);
// Temp Defaults
// Setup defaults
// Set Margins to 1" all around
PrinterInfo.rcMargins.top =
PrinterInfo.rcMargins.bottom =
PrinterInfo.rcMargins.left =
PrinterInfo.rcMargins.right = (int)(INCH * (PrinterInfo.ptResolution.x * 0.01));
// Start at upper left hand corner
PageInfo.ptCurrentPos.x = PrinterInfo.rcMargins.left;
PageInfo.ptCurrentPos.y = PrinterInfo.rcMargins.top;
// Default Tab Stops = 1/2"
PageInfo.nTabStop = (int)(HALF_INCH * (PrinterInfo.ptResolution.x * 0.01));
// Default Paragraph Spacing
ParagraphInfo.nSpaceBefore = (int)(QUARTER_INCH * (PrinterInfo.ptResolution.y * 0.01));
// No Indent By Default
ParagraphInfo.nLeftIndent = 0;
return TRUE;
}
else
{
DoCommDlgError(hWnd, CommDlgExtendedError());
return FALSE;
}
}
/*************************************************************************
Setup for the start of a paragraph, set text attributes
*************************************************************************/
int FAR PASCAL StartParagraph(LPSTR szFontName, int nFontSize, int nStyle)
{
int nFontWeight; // Weight of the font
BYTE bFontItalic; // Italic flag
// Check for bogus font size values
nFontSize = min(nFontSize, MAX_FONT_SIZE); // No bigger than
nFontSize = max(nFontSize, MIN_FONT_SIZE); // No smaller than
// Get weight of font
if(nStyle & BOLD_FONT) nFontWeight = FW_BOLD;
else nFontWeight = FW_NORMAL;
// Get font slant
if(nStyle & ITALIC_FONT) bFontItalic = 1;
else bFontItalic = 0;
// Remember Border Style and Size
ParagraphInfo.nStyle = nStyle;
ParagraphInfo.wBorderWidth = (WORD)(((PrinterInfo.ptResolution.x * BORDER_WIDTH) / 72) << 8);
ParagraphInfo.wBorderWidth += (WORD)((PrinterInfo.ptResolution.y * BORDER_WIDTH) / 72);
// Setup Text Attributes
SetBkMode(ppPrinter.hDC, TRANSPARENT); // Show whatever was there before through the text
SetTextColor(ppPrinter.hDC, 0); // Black Text
SetBkColor(ppPrinter.hDC, 0x00FFFFFF); // White Background
SetTextAlign(ppPrinter.hDC, TA_TOP|TA_LEFT); // Text aligned at top, left of bounding box
ParagraphInfo.hFont = CreateFont((int)((PrinterInfo.ptResolution.y * nFontSize) / 72),
0, 0, 0,
nFontWeight,
bFontItalic,
0, 0,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
VARIABLE_PITCH | FF_DONTCARE,
szFontName);
if(ParagraphInfo.hFont) // If we get the font, selected and get the metrics and width
{
ParagraphInfo.hOldFont = SelectObject(ppPrinter.hDC, ParagraphInfo.hFont);
GetTextMetrics(ppPrinter.hDC, (LPTEXTMETRIC)&ParagraphInfo.tm);
GetCharWidth(ppPrinter.hDC, FIRST_CHAR, LAST_CHAR, (LPINT)&ParagraphInfo.nWidth);
}
// Set Current Line Width to Zero
PageInfo.dwCurLineWidth = 0;
// See if first line will fit on page
if((PageInfo.ptCurrentPos.y += ParagraphInfo.nSpaceBefore) > (PrinterInfo.ptPageSize.y - PrinterInfo.rcMargins.bottom - ParagraphInfo.tm.tmHeight - ParagraphInfo.tm.tmExternalLeading))
{
EjectPage(); // Sets current positon too
}
// Get Indent/Check Box Info
if(nStyle & CHECK_BOX)
{
WORD wBorderWidth;
wBorderWidth = ParagraphInfo.wBorderWidth; // Save the current Border width
SetBorderWidth(0);
// Set Indent Value
ParagraphInfo.nLeftIndent = (int)(QUARTER_INCH * (PrinterInfo.ptResolution.x * 0.01)); // Default Paragraph Indent
// Draw Check Box
FDrawRectangle( ppPrinter.hDC,
PrinterInfo.rcMargins.left,
PageInfo.ptCurrentPos.y + ParagraphInfo.tm.tmExternalLeading,
PrinterInfo.rcMargins.left + (int)(EIGHTH_INCH * (PrinterInfo.ptResolution.x * 0.01)),
PageInfo.ptCurrentPos.y + (int)(EIGHTH_INCH * (PrinterInfo.ptResolution.y * 0.01)) + ParagraphInfo.tm.tmExternalLeading);
ParagraphInfo.wBorderWidth = wBorderWidth; // Restore Border width
}
else
{
ParagraphInfo.nLeftIndent = 0;
}
if(ParagraphInfo.nStyle & TOP_BORDER) // Top Border Line
FDrawLine( ppPrinter.hDC,
PrinterInfo.rcMargins.left - (int)(HIBYTE(ParagraphInfo.wBorderWidth)),
PageInfo.ptCurrentPos.y - (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2),
PrinterInfo.ptPageSize.x - PrinterInfo.rcMargins.right + (int)(HIBYTE(ParagraphInfo.wBorderWidth)),
PageInfo.ptCurrentPos.y - (int)(LOBYTE(ParagraphInfo.wBorderWidth)/2));
// Width of column to print into
ParagraphInfo.dwWidth = PrinterInfo.ptPageSize.x -
PrinterInfo.rcMargins.left -
PrinterInfo.rcMargins.right -
ParagraphInfo.nLeftIndent;
// Start at left margin
PageInfo.ptCurrentPos.x = PrinterInfo.rcMargins.left + ParagraphInfo.nLeftIndent;
if(ParagraphInfo.hFont) // If the font was generated, then we're cool
return TRUE;
else // Otherwise we're not
return FALSE;
}
/*************************************************************************
Print the actual paragraph taking in to consideration tab's
returns, etc...
*************************************************************************/
int FAR PASCAL ParagraphText(LPSTR szText)
{
char far *cpStart; // Pointer in string to print
char far *cpCurrent;
char far *cpEnd;
HGLOBAL hText;
LPSTR lpText;
PageInfo.bPageDirty = TRUE;
// Get our own private copy of the text
hText = GlobalAlloc(GHND, lstrlen((LPSTR)szText)+1);
if(!hText) return FALSE;
lpText = GlobalLock(hText);
if(!lpText) return FALSE;
lstrcpy((LPSTR)lpText, (LPSTR) szText);
cpStart = cpCurrent = cpEnd = (LPSTR)lpText; // All pointers to the start of the text string
if(cpStart == NULL) return TRUE; // If the string is NULL, thats alright, just don't do anything
while(*cpCurrent != NULL)
{
switch(*cpCurrent)
{
/* TAB */ case '\t' : cpEnd = cpCurrent;
*cpEnd = 0; // Set end of string to null
TextOutAtCurPos((LPSTR)cpStart); // Print text up to tab
PageInfo.ptCurrentPos.x += LOWORD(GetTextExtent(ppPrinter.hDC, (LPSTR)cpStart, lstrlen((LPSTR)cpStart)));
PageInfo.ptCurrentPos.x = (PageInfo.nTabStop * ((PageInfo.ptCurrentPos.x / PageInfo.nTabStop)+1));
PageInfo.dwCurLineWidth = PageInfo.ptCurrentPos.x - PrinterInfo.rcMargins.left;
cpStart = cpCurrent = cpEnd+1;
break;
/* CR */ case '\r' : cpEnd = cpCurrent;
*cpEnd = 0; // Set end of string to null
TextOutAtCurPos((LPSTR)cpStart); // Print the text
// Next Line Down
PageInfo.ptCurrentPos.y += ParagraphInfo.tm.tmHeight + ParagraphInfo.tm.tmExternalLeading;
if(PageInfo.ptCurrentPos.y > PrinterInfo.ptPageSize.y - PrinterInfo.rcMargins.bottom - ParagraphInfo.tm.tmHeight - ParagraphInfo.tm.tmExternalLeading)
{
EjectPage();
}
// Start at left margin
PageInfo.ptCurrentPos.x = PrinterInfo.rcMargins.left + ParagraphInfo.nLeftIndent;
cpStart = cpCurrent = cpEnd+1; // Set everything to start of next line
if(*cpStart == '\n') // Get rid of those dang line feeds
cpStart = cpEnd = ++cpCurrent;
// Clear Width
PageInfo.dwCurLineWidth = 0;
break;
/* NULL */ case NULL : cpEnd = cpCurrent; goto showline;
break;
default : if(*cpCurrent < FIRST_CHAR) *cpCurrent = ' '; // Set any control chars to space
PageInfo.dwCurLineWidth += ParagraphInfo.nWidth[(int)(*cpCurrent) - FIRST_CHAR]; // Width of character
if(*cpCurrent == ' ') cpEnd = cpCurrent; // Space is always an excuse to break a line
cpCurrent++; // Goto next character
break;
}
if( PageInfo.dwCurLineWidth > ParagraphInfo.dwWidth && (cpStart != cpEnd)) // Wrap Line
{
*cpEnd = 0; // Set end of string to null
TextOutAtCurPos((LPSTR)cpStart);
// Next Line Down
PageInfo.ptCurrentPos.y += ParagraphInfo.tm.tmHeight + ParagraphInfo.tm.tmExternalLeading;
if(PageInfo.ptCurrentPos.y > PrinterInfo.ptPageSize.y - PrinterInfo.rcMargins.bottom - ParagraphInfo.tm.tmHeight - ParagraphInfo.tm.tmExternalLeading)
{
EjectPage();
}
// Start at left margin
PageInfo.ptCurrentPos.x = PrinterInfo.rcMargins.left + ParagraphInfo.nLeftIndent;
cpStart = cpCurrent = cpEnd+1; // Set everything to start of next line
PageInfo.dwCurLineWidth = 0; // Clear Width
}
}
showline:
if(*cpStart) // No Text, so don't print it
{
TextOutAtCurPos((LPSTR) cpStart);
PageInfo.ptCurrentPos.x += (int)PageInfo.dwCurLineWidth; // Set current X position
}
else // We still have to put the border around the current line
{
if(ParagraphInfo.nStyle & LEFT_BORDER) // Left border
FDrawLine( ppPrinter.hDC,
PrinterInfo.rcMargins.left - (int)((HIBYTE(ParagraphInfo.wBorderWidth))),
PageInfo.ptCurrentPos.y - (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2),
PrinterInfo.rcMargins.left - (int)((HIBYTE(ParagraphInfo.wBorderWidth))),
PageInfo.ptCurrentPos.y + ParagraphInfo.tm.tmHeight + ParagraphInfo.tm.tmExternalLeading + (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2));
if(ParagraphInfo.nStyle & RIGHT_BORDER) // Right border
FDrawLine( ppPrinter.hDC,
PrinterInfo.ptPageSize.x - PrinterInfo.rcMargins.right + (int)((HIBYTE(ParagraphInfo.wBorderWidth))),
PageInfo.ptCurrentPos.y - (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2),
PrinterInfo.ptPageSize.x - PrinterInfo.rcMargins.right + (int)((HIBYTE(ParagraphInfo.wBorderWidth))),
PageInfo.ptCurrentPos.y + ParagraphInfo.tm.tmHeight + ParagraphInfo.tm.tmExternalLeading + (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2));
}
GlobalUnlock(hText);
GlobalFree(hText);
return TRUE;
}
/*************************************************************************
Clean up after printing a paragraph of text
*************************************************************************/
int FAR PASCAL FinishParagraph(void)
{
SelectObject(ppPrinter.hDC, ParagraphInfo.hOldFont);
DeleteObject(ParagraphInfo.hFont);
// Next Line Down
PageInfo.ptCurrentPos.y += ParagraphInfo.tm.tmHeight + ParagraphInfo.tm.tmExternalLeading;
// Bottom Border Line
if(ParagraphInfo.nStyle & BOTTOM_BORDER)
FDrawLine( ppPrinter.hDC,
PrinterInfo.rcMargins.left - (int)(HIBYTE(ParagraphInfo.wBorderWidth)),
PageInfo.ptCurrentPos.y + (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2),
PrinterInfo.ptPageSize.x - PrinterInfo.rcMargins.right + (int)(HIBYTE(ParagraphInfo.wBorderWidth)),
PageInfo.ptCurrentPos.y + (int)(LOBYTE(ParagraphInfo.wBorderWidth)/2));
if((PageInfo.ptCurrentPos.y += ParagraphInfo.nSpaceAfter) > (PrinterInfo.ptPageSize.y - PrinterInfo.rcMargins.bottom))
{
EjectPage(); // Sets current positon too
}
if(PageInfo.ptCurrentPos.y > PrinterInfo.ptPageSize.y - PrinterInfo.rcMargins.bottom - ParagraphInfo.tm.tmHeight - ParagraphInfo.tm.tmExternalLeading)
{
EjectPage();
}
// Start at left margin
PageInfo.ptCurrentPos.x = PrinterInfo.rcMargins.left + ParagraphInfo.nLeftIndent;
return TRUE;
}
/*************************************************************************
Internal function to print a line of text at a specific position.
*************************************************************************/
int TextOutAtCurPos(LPSTR szText)
{
RECT rc;
int nRetVal;
if(ParagraphInfo.nStyle & LEFT_BORDER) // Left border
FDrawLine( ppPrinter.hDC,
PrinterInfo.rcMargins.left - (int)(HIBYTE(ParagraphInfo.wBorderWidth)),
PageInfo.ptCurrentPos.y - (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2),
PrinterInfo.rcMargins.left - (int)(HIBYTE(ParagraphInfo.wBorderWidth)),
PageInfo.ptCurrentPos.y + ParagraphInfo.tm.tmHeight + ParagraphInfo.tm.tmExternalLeading + (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2));
if(ParagraphInfo.nStyle & RIGHT_BORDER) // Right border
FDrawLine( ppPrinter.hDC,
PrinterInfo.ptPageSize.x - PrinterInfo.rcMargins.right + (int)(HIBYTE(ParagraphInfo.wBorderWidth)),
PageInfo.ptCurrentPos.y - (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2),
PrinterInfo.ptPageSize.x - PrinterInfo.rcMargins.right + (int)(HIBYTE(ParagraphInfo.wBorderWidth)),
PageInfo.ptCurrentPos.y + ParagraphInfo.tm.tmHeight + ParagraphInfo.tm.tmExternalLeading + (int)((LOBYTE(ParagraphInfo.wBorderWidth))/2));
SetRect((LPRECT)&rc,
(int)PageInfo.ptCurrentPos.x - PrinterInfo.rcUnprintable.left,
(int)PageInfo.ptCurrentPos.y - PrinterInfo.rcUnprintable.top,
(int)PrinterInfo.ptPageSize.x - PrinterInfo.rcMargins.right - PrinterInfo.rcUnprintable.left,
(int)PageInfo.ptCurrentPos.y - PrinterInfo.rcUnprintable.top + ParagraphInfo.tm.tmHeight + ParagraphInfo.tm.tmExternalLeading);
nRetVal = ExtTextOut( ppPrinter.hDC,
PageInfo.ptCurrentPos.x - PrinterInfo.rcUnprintable.left,
PageInfo.ptCurrentPos.y - PrinterInfo.rcUnprintable.top,
ETO_OPAQUE,
(LPRECT)&rc,
szText,
lstrlen(szText),
NULL);
return nRetVal;
}
/*************************************************************************
Draw an Ellipse
*************************************************************************/
int FDrawEllipse(HDC hDC, int nStartX, int nStartY, int nEndX, int nEndY)
{
int nRet=FALSE;
HPEN hPen, hOldPen;
// Black Pen
hPen = CreatePen(0,LOBYTE(ParagraphInfo.wBorderWidth),0);
if(hPen)
{
hOldPen = SelectObject(hDC, hPen);
nRet = Ellipse( hDC,
nStartX - PrinterInfo.rcUnprintable.left,
nStartY - PrinterInfo.rcUnprintable.top,
nEndX - PrinterInfo.rcUnprintable.left,
nEndY - PrinterInfo.rcUnprintable.top);
SelectObject(hDC, hOldPen);
DeleteObject(hPen);
}
return nRet;
}
/*************************************************************************
Draw a Rectangele with Rounded Corners
*************************************************************************/
int FDrawRndRectangle(HDC hDC, int nStartX, int nStartY, int nEndX, int nEndY, int nElpX, int nElpY)
{
int nRet=FALSE;
HPEN hPen, hOldPen;
// Black Pen
hPen = CreatePen(0,LOBYTE(ParagraphInfo.wBorderWidth),0);
if(hPen)
{
hOldPen = SelectObject(hDC, hPen);
nRet = RoundRect( hDC,
nStartX - PrinterInfo.rcUnprintable.left,
nStartY - PrinterInfo.rcUnprintable.top,
nEndX - PrinterInfo.rcUnprintable.left,
nEndY - PrinterInfo.rcUnprintable.top,
nElpX,
nElpY);
SelectObject(hDC, hOldPen);
DeleteObject(hPen);
}
return nRet;
}
/*************************************************************************
Draw a Rectangle with Square Corners
*************************************************************************/
int FDrawRectangle(HDC hDC, int nStartX, int nStartY, int nEndX, int nEndY)
{
int nRet=FALSE;
HPEN hPen, hOldPen;
// Black Pen
hPen = CreatePen(0,LOBYTE(ParagraphInfo.wBorderWidth),0);
if(hPen)
{
hOldPen = SelectObject(hDC, hPen);
nRet = Rectangle( hDC,
nStartX - PrinterInfo.rcUnprintable.left,
nStartY - PrinterInfo.rcUnprintable.top,
nEndX - PrinterInfo.rcUnprintable.left,
nEndY - PrinterInfo.rcUnprintable.top);
SelectObject(hDC, hOldPen);
DeleteObject(hPen);
}
return nRet;
}
/*************************************************************************
Draw a line
*************************************************************************/
int FDrawLine(HDC hDC, int nStartX, int nStartY, int nEndX, int nEndY)
{
int nRet=FALSE;
HPEN hPen, hOldPen;
hPen = CreatePen(0,LOBYTE(ParagraphInfo.wBorderWidth),0);
if(hPen)
{
hOldPen = SelectObject(hDC, hPen);
MoveTo( hDC,
nStartX - PrinterInfo.rcUnprintable.left,
nStartY - PrinterInfo.rcUnprintable.top);
nRet = LineTo( hDC,
(int)nEndX - PrinterInfo.rcUnprintable.left,
(int)nEndY - PrinterInfo.rcUnprintable.top);
SelectObject(hDC, hOldPen);
DeleteObject(hPen);
}
return nRet;
}
/*************************************************************************
Print a Headline which is just a special case of a paragraph,
makes all setup and clean up calls for you.
*************************************************************************/
int FAR PASCAL PrintHeadline(LPSTR szHeadLine, LPSTR szFontName, int nFontSize, int nStyle)
{
StartParagraph(szFontName, nFontSize, nStyle);
ParagraphText(szHeadLine);
FinishParagraph();
return TRUE;
}
/*************************************************************************
End of printing function, cleans up memory and ejects the last page
*************************************************************************/
int FAR PASCAL DonePrinting(void)
{
int nRet=FALSE;
Escape(ppPrinter.hDC,NEWFRAME, 0, 0L, 0L); // Kick out last page
Escape(ppPrinter.hDC,ENDDOC, 0, 0L, 0L);
FreeProcInstance(lpfnAbortProc);
nRet = DeleteDC(ppPrinter.hDC);
if (ppPrinter.hDevMode != NULL)
{
GlobalFree(ppPrinter.hDevMode);
ppPrinter.hDevMode = NULL;
}
if (ppPrinter.hDevNames != NULL)
{
GlobalFree(ppPrinter.hDevNames);
ppPrinter.hDevNames = NULL;
}
return nRet;
}
/*************************************************************************
Unconditionally ejects page from printer, then sets the current page
position to upper left corner, this also restores the currently
selected font.
*************************************************************************/
int FAR PASCAL EjectPage(void)
{
int nRet;
HFONT hFont;
// Save Currently selected Font
hFont = SelectObject(ppPrinter.hDC, GetStockObject(DEVICE_DEFAULT_FONT));
nRet = Escape(ppPrinter.hDC,NEWFRAME, 0, 0L, 0L); // Kick out page
// Restore Currently select Font
SelectObject(ppPrinter.hDC, hFont);
PageInfo.ptCurrentPos.x = PrinterInfo.rcMargins.left; // Start at upper left hand corner
PageInfo.ptCurrentPos.y = PrinterInfo.rcMargins.top;
PageInfo.bPageDirty = FALSE; // Page is no longer dirty
return nRet;
}
/*************************************************************************
Sets margins for pages printed after this function is called.
*************************************************************************/
int FAR PASCAL PageLayoutSetup(int nTop, int nRight, int nBottom, int nLeft)
{
nTop = min(nTop, 2 * INCH); // No bigger than
nTop = max(nTop, 0); // No smaller than
nBottom = min(nBottom, 2 * INCH); // No bigger than
nBottom = max(nBottom, 0); // No smaller than
nLeft = min(nLeft, 2 * INCH); // No bigger than
nLeft = max(nLeft, 0); // No smaller than
nRight = min(nRight, 2 * INCH); // No bigger than
nRight = max(nRight, 0); // No smaller than
PrinterInfo.rcMargins.top = (int)(nTop * (int)(PrinterInfo.ptResolution.y * 0.01));
PrinterInfo.rcMargins.bottom = (int)(nBottom * (int)(PrinterInfo.ptResolution.y * 0.01));
PrinterInfo.rcMargins.left = (int)(nLeft * (int)(PrinterInfo.ptResolution.x * 0.01));
PrinterInfo.rcMargins.right = (int)(nRight * (int)(PrinterInfo.ptResolution.x * 0.01));
PageInfo.ptCurrentPos.x = PrinterInfo.rcMargins.left; // Start at upper left hand corner
PageInfo.ptCurrentPos.y = PrinterInfo.rcMargins.top;
return TRUE;
}
/*************************************************************************
This procedure brings up a message box with Common Dialog error text
*************************************************************************/
BOOL DoCommDlgError(HWND hWnd, DWORD dwError)
{
char sz1[80];
char sz2[32];
if(dwError != 0)
{
LoadString(hInst, (WORD)dwError, sz2, 32);
if(!sz2[0])
lstrcpy(sz2,"Unknown");
wsprintf(sz1," Error: %s ",(LPSTR)sz2);
MessageBox(hWnd,sz1," COMMDLG.DLL ERROR ",MB_ICONSTOP);
return TRUE;
}
else
return FALSE;
}
/*************************************************************************
Fills the PrinterInfo structure with the printers current
unprintable region
*************************************************************************/
BOOL GetUnprintableRegion(HDC hDCPrn)
{
RECT rcTemp;
POINT ptPhysPageSize;
POINT ptOffset;
Escape(hDCPrn, GETPHYSPAGESIZE, NULL, (LPSTR)NULL, (LPSTR) &ptPhysPageSize);
Escape(hDCPrn, GETPRINTINGOFFSET, NULL, (LPSTR)NULL, (LPSTR) &ptOffset);
GetClipBox(hDCPrn,&rcTemp); // Size of Printable region
PrinterInfo.ptPageSize.x = ptPhysPageSize.x;
PrinterInfo.ptPageSize.y = ptPhysPageSize.y;
PrinterInfo.rcUnprintable.top = ptOffset.y;
PrinterInfo.rcUnprintable.left = ptOffset.x;
PrinterInfo.rcUnprintable.right = ptPhysPageSize.x - ptOffset.x;
PrinterInfo.rcUnprintable.bottom = ptPhysPageSize.y - ptOffset.y;
return TRUE;
}
/*************************************************************************
Sticks the printers current resolution in the PrinterInfo Structure
*************************************************************************/
BOOL GetPrinterResolution(HDC hDCPrn)
{
PrinterInfo.ptResolution.x = GetDeviceCaps(hDCPrn, LOGPIXELSX);
PrinterInfo.ptResolution.y = GetDeviceCaps(hDCPrn, LOGPIXELSY);
return TRUE;
}
/*************************************************************************
Abort Proc for printing, this is where control is returned to the
system during printing. Gets called by the printer driver
periocically for control release purposes.
*************************************************************************/
BOOL FAR PASCAL PrnAbortProc(HDC hDCPrn, short nCode)
{
MSG msg;
while(!fAbort && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return !fAbort;
}
/*************************************************************************
Returns version number of the Print DLL
*************************************************************************/
int FAR PASCAL PrintDLLVersion(VOID)
{
return ((MAJOR_VERSION) | (MINOR_VERSION << 8));
}
/*************************************************************************
Sets the space before and after a paragraph
*************************************************************************/
BOOL FAR PASCAL SetParagraphSpacing(int nSpaceBefore, int nSpaceAfter)
{
// Check for bogus Spacing size values
nSpaceBefore = min(nSpaceBefore, MAX_FONT_SIZE); // No bigger than
nSpaceBefore = max(nSpaceBefore, MIN_FONT_SIZE); // No smaller than
ParagraphInfo.nSpaceBefore = (int)((PrinterInfo.ptResolution.y * nSpaceBefore) / 72);
// Check for bogus Spacing size values
nSpaceAfter = min(nSpaceAfter, MAX_FONT_SIZE); // No bigger than
nSpaceAfter = max(nSpaceAfter, MIN_FONT_SIZE); // No smaller than
ParagraphInfo.nSpaceAfter = (int)((PrinterInfo.ptResolution.y * nSpaceAfter) / 72);
return TRUE;
}
/*************************************************************************
Sets Line Weight for borders
*************************************************************************/
BOOL FAR PASCAL SetBorderWidth(int nWidth)
{
if(nWidth !=0)
{
// Check for bogus Width values
nWidth = min(nWidth, MAX_WIDTH_SIZE); // No bigger than
nWidth = max(nWidth, MIN_WIDTH_SIZE); // No smaller than
ParagraphInfo.wBorderWidth = (WORD)(((PrinterInfo.ptResolution.x * nWidth) / 72) << 8);
ParagraphInfo.wBorderWidth += (WORD)((PrinterInfo.ptResolution.y * nWidth) / 72);
}
else // Gaurentee 1 pixel width
{
ParagraphInfo.wBorderWidth = (WORD)((1) << 8);
ParagraphInfo.wBorderWidth += (WORD)(1);
}
return TRUE;
}
/*************************************************************************
Prints headers for a set of columns
*************************************************************************/
int FAR PASCAL PrintColumnHeaders(LPSTR szHeader, int nNumColumns, LPINT nC, LPSTR szFontName, int nFontSize, int nStyle)
{
SetUpColumns(nNumColumns, nC, szFontName, nFontSize, nStyle);
PrintColumnText(szHeader);
EndColumnPrinting();
return TRUE;
}
/*************************************************************************
Sets up the number and widths of columns to be printed
*************************************************************************/
int FAR PASCAL SetUpColumns(int nNumColumns, LPINT nC, LPSTR szFontName, int nFontSize, int nStyle)
{
int nFontWeight; // Weight of the font
BYTE bFontItalic; // Italic flag
// Remember these
ColumnInfo.nNumColumns = nNumColumns;
ColumnInfo.rgColumnWidths[0] = nC[0];
ColumnInfo.rgColumnWidths[1] = nC[1];
ColumnInfo.rgColumnWidths[2] = nC[2];
ColumnInfo.rgColumnWidths[3] = nC[3];
ColumnInfo.rgColumnWidths[4] = nC[4];
ColumnInfo.rgColumnWidths[5] = nC[5];
ColumnInfo.rgColumnWidths[6] = nC[6];
ColumnInfo.rgColumnWidths[7] = nC[7];
// Check for bogus font size values
nFontSize = min(nFontSize, MAX_FONT_SIZE); // No bigger than
nFontSize = max(nFontSize, MIN_FONT_SIZE); // No smaller than
// Get weight of font
if(nStyle & BOLD_FONT) nFontWeight = FW_BOLD;
else nFontWeight = FW_NORMAL;
// Get font slant
if(nStyle & ITALIC_FONT) bFontItalic = 1;
else bFontItalic = 0;
// Remember Border Style and Size
ColumnInfo.nStyle = nStyle;
ColumnInfo.wBorderWidth = (WORD)(((PrinterInfo.ptResolution.x * BORDER_WIDTH) / 72) << 8);
ColumnInfo.wBorderWidth += (WORD)((PrinterInfo.ptResolution.y * BORDER_WIDTH) / 72);
// Setup Text Attributes
SetBkMode(ppPrinter.hDC, TRANSPARENT); // Show whatever was there before through the text
SetTextColor(ppPrinter.hDC, 0); // Black Text
SetBkColor(ppPrinter.hDC, 0x00FFFFFF); // White Background
SetTextAlign(ppPrinter.hDC, TA_TOP|TA_LEFT); // Text aligned at top, left of bounding box
ColumnInfo.hFont = CreateFont((int)((PrinterInfo.ptResolution.y * nFontSize) / 72),
0, 0, 0,
nFontWeight,
bFontItalic,
0, 0,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
VARIABLE_PITCH | FF_DONTCARE,
szFontName);
if(ColumnInfo.hFont) // If we get the font, selected and get the metrics and width
{
ColumnInfo.hOldFont = SelectObject(ppPrinter.hDC, ColumnInfo.hFont);
GetTextMetrics(ppPrinter.hDC, (LPTEXTMETRIC)&ColumnInfo.tm);
GetCharWidth(ppPrinter.hDC, FIRST_CHAR, LAST_CHAR, (LPINT)&ColumnInfo.nWidth);
}
return TRUE;
}
/*************************************************************************
Printed text in columns, the text is seperated by
tab (0x09) characters
*************************************************************************/
int FAR PASCAL PrintColumnText(LPSTR szText)
{
int nColumnCount;
int nMaxRowHeight;
int nLineCount;
int nSpaceCount;
int nOffset;
RECT rc;
char FAR *cpColText;
char FAR *cpBegin;
char FAR *cpCurrent;
char FAR *rgcpColText[MAX_COLUMNS];
int nColCount;
DWORD dwWidth, dwColumnWidth;
HGLOBAL hText;
LPSTR lpText;
PageInfo.bPageDirty = TRUE;
// Get our own private copy of the text
hText = GlobalAlloc(GHND, lstrlen((LPSTR)szText)+1);
if(!hText) return FALSE;
lpText = (LPSTR)GlobalLock(hText);
if(!lpText) return FALSE;
lstrcpy((LPSTR)lpText, (LPSTR)szText);
// Calculate where all the strings are
cpColText = (LPSTR)lpText;
nColCount = 0;
rgcpColText[nColCount++] = (LPSTR)cpColText; // First Column;
// Setup pointers to each column of text
while(*cpColText != NULL)
{
if(*cpColText == '\t')
{
*cpColText = NULL; // NULL Terminate
cpColText++;
rgcpColText[nColCount++] = (LPSTR)cpColText;
}
else
{
cpColText++;
}
}
// Calculate the Max Height of the cells
nMaxRowHeight = 1;
for(nColumnCount = 0; nColumnCount < ColumnInfo.nNumColumns; nColumnCount++)
{
cpBegin = cpCurrent = rgcpColText[nColumnCount];
dwColumnWidth = (DWORD)(ColumnInfo.rgColumnWidths[nColumnCount] * (PrinterInfo.ptResolution.x * 0.01));
dwWidth = 0;
nSpaceCount = -1;
nLineCount = 1;
while(*cpCurrent != NULL)
{
dwWidth += ColumnInfo.nWidth[(int)(*cpCurrent) - FIRST_CHAR]; // Width of Character
switch(*cpCurrent)
{
case ' ' : if(dwWidth > dwColumnWidth)
{
nLineCount++;
if(nSpaceCount >= 0)
{
cpCurrent = cpBegin;
nSpaceCount = -1;
}
else
cpCurrent++;
dwWidth = 0;
}
else
{
nSpaceCount++;
cpBegin = ++cpCurrent;
}
break;
case '\r': cpBegin = ++cpCurrent;
nLineCount++;
break;
default : cpCurrent++;
break;
}
}
if(dwWidth > dwColumnWidth) nLineCount++; // In case of any left overs
nMaxRowHeight = max(nMaxRowHeight, nLineCount);
}
nMaxRowHeight *= ColumnInfo.tm.tmHeight;
// See if first line will fit on page
if((PageInfo.ptCurrentPos.y + nMaxRowHeight) > (PrinterInfo.ptPageSize.y - PrinterInfo.rcMargins.top - PrinterInfo.rcMargins.bottom))
{
EjectPage(); // Sets current positon too
}
SetBorderWidth(0);
for(nColumnCount = 0; nColumnCount < ColumnInfo.nNumColumns; nColumnCount++)
{
nOffset = GetColumnOffset(nColumnCount);
SetRect( &rc,
PrinterInfo.rcMargins.left + nOffset,
PageInfo.ptCurrentPos.y,
PrinterInfo.rcMargins.left + nOffset + (int)(ColumnInfo.rgColumnWidths[nColumnCount] * (PrinterInfo.ptResolution.x * 0.01)),
PageInfo.ptCurrentPos.y + nMaxRowHeight);
if(ColumnInfo.nStyle & TOP_BORDER)
{
// Draw Top Border
FDrawLine(ppPrinter.hDC, rc.left, rc.top, rc.right, rc.top);
}
if(ColumnInfo.nStyle & LEFT_BORDER)
{
// Draw Left Border
FDrawLine(ppPrinter.hDC, rc.left, rc.top, rc.left, rc.bottom);
}
if(ColumnInfo.nStyle & RIGHT_BORDER)
{
// Draw Right Border
FDrawLine(ppPrinter.hDC, rc.right, rc.top, rc.right, rc.bottom);
}
if(ColumnInfo.nStyle & BOTTOM_BORDER)
{
// Draw Bottom Border
FDrawLine(ppPrinter.hDC, rc.left, rc.bottom, rc.right, rc.bottom);
}
rc.left += 1; // Get Text Within Borders
rc.top += 1;
rc.right -= 1;
rc.bottom -= 1;
CellDrawText(ppPrinter.hDC, (LPSTR)rgcpColText[nColumnCount], (LPRECT)&rc);
}
PageInfo.ptCurrentPos.y += nMaxRowHeight;
GlobalUnlock(hText);
GlobalFree(hText);
return TRUE;
}
/*************************************************************************
Ends column printing and does cleanup
*************************************************************************/
int FAR PASCAL EndColumnPrinting(VOID)
{
SelectObject(ppPrinter.hDC, ColumnInfo.hOldFont);
DeleteObject(ColumnInfo.hFont);
return TRUE;
}
/*************************************************************************
Calculates the Left Offset of the given column from the left
edge of the first column
*************************************************************************/
int GetColumnOffset(int nColumn)
{
int nOffset=0;
int nTemp;
if(nColumn == 0) return nOffset;
for(nTemp=0; nTemp < nColumn; nTemp++)
{
nOffset += (int)(ColumnInfo.rgColumnWidths[nTemp] * (PrinterInfo.ptResolution.x * 0.01));
}
return nOffset;
}
/*************************************************************************
Prints Text on Physical page given logical co-ordinates
*************************************************************************/
int CellDrawText(HDC hDC, LPSTR szText, LPRECT rc)
{
RECT rcTemp;
rcTemp.top = rc->top - PrinterInfo.rcUnprintable.top;
rcTemp.bottom = rc->bottom - PrinterInfo.rcUnprintable.top;
rcTemp.left = rc->left - PrinterInfo.rcUnprintable.left;
rcTemp.right = rc->right - PrinterInfo.rcUnprintable.left;
DrawText(hDC, (LPSTR)szText, lstrlen((LPSTR)szText), (LPRECT)&rcTemp, DT_TOP | DT_WORDBREAK);
return TRUE;
}
/*************************************************************************
Internal function to retrieve the Device Context of the current
Printer Driver
*************************************************************************/
HDC GetPrinterDC(void)
{
static char szPrinter[80];
char *szDevice, *szDriver, *szOutput;
GetProfileString("windows", "device",",,,",szPrinter, 80);
if( (szDevice = strtok(szPrinter,"," )) &&
(szDriver = strtok(NULL, ", ")) &&
(szOutput = strtok(NULL, ", ")))
{
return CreateDC(szDriver, szDevice, szOutput, NULL);
}
return FALSE;
}
/*************************************************************************
Unconditionally kills the current print job
*************************************************************************/
BOOL FAR PASCAL KillJob(void)
{
fAbort = TRUE;
return fAbort;
}
/*************************************************************************
Returns the name of the current Printer
*************************************************************************/
BOOL FAR PASCAL PrinterName(LPSTR szDevName)
{
DEVMODE FAR *lpDevmode;
/* Initialize the necessary PRINTDLG structure members. */
ppPrinter.lStructSize = sizeof(PRINTDLG);
ppPrinter.Flags = PD_RETURNDEFAULT;
if(ppPrinter.hDevMode)
{
lpDevmode = (DEVMODE FAR *)GlobalLock(ppPrinter.hDevMode);
lstrcpy(szDevName,(LPSTR)lpDevmode->dmDeviceName);
GlobalUnlock(ppPrinter.hDevMode);
return TRUE;
}
if (PrintDlg(&ppPrinter) != 0)
{
lpDevmode = (DEVMODE FAR *)GlobalLock(ppPrinter.hDevMode);
lstrcpy(szDevName,(LPSTR)lpDevmode->dmDeviceName);
GlobalUnlock(ppPrinter.hDevMode);
return TRUE;
}
else
{
DoCommDlgError(hWndApp, CommDlgExtendedError());
return FALSE;
}
}
/*************************************************************************
Returns the port to which the current printer is connected
*************************************************************************/
BOOL FAR PASCAL PrinterPort(LPSTR szPortName)
{
DEVNAMES FAR *lpDevnames;
// Initialize the necessary PRINTDLG structure members.
ppPrinter.lStructSize = sizeof(PRINTDLG);
ppPrinter.Flags = PD_RETURNDEFAULT;
if(ppPrinter.hDevNames)
{
lpDevnames = (DEVNAMES FAR *)GlobalLock(ppPrinter.hDevNames);
lstrcpy(szPortName,(LPSTR)lpDevnames + lpDevnames->wOutputOffset);
GlobalUnlock(ppPrinter.hDevNames);
return TRUE;
}
if (PrintDlg(&ppPrinter) != 0)
{
lpDevnames = (DEVNAMES FAR *)GlobalLock(ppPrinter.hDevNames);
lstrcpy(szPortName,(LPSTR)lpDevnames + lpDevnames->wOutputOffset);
GlobalUnlock(ppPrinter.hDevNames);
return TRUE;
}
else
{
DoCommDlgError(hWndApp, CommDlgExtendedError());
return FALSE;
}
}
/*************************************************************************
Returns TRUE if there are objects on the page, FALSE if the page is
empty.
*************************************************************************/
BOOL FAR PASCAL IsPageDirty(void)
{
return PageInfo.bPageDirty;
}
/*************************************************************************
Returns the current Vertical cursor location in TWIPS
*************************************************************************/
int FAR PASCAL PagePosY(void)
{
return ((PageInfo.ptCurrentPos.y/PrinterInfo.ptResolution.y)*72*20);
}
/*************************************************************************
Returns the current Horizontal cursor location in TWIPS
*************************************************************************/
int FAR PASCAL PagePosX(void)
{
return ((PageInfo.ptCurrentPos.x/PrinterInfo.ptResolution.x)*72*20);
}
/*************************************************************************
Returns the vertical page size is TWIPS
*************************************************************************/
int FAR PASCAL PageSizeY(void)
{
return ((PrinterInfo.ptPageSize.y/PrinterInfo.ptResolution.y)*72*20);
}
/*************************************************************************
Returns the horizontal page size in TWIPS
*************************************************************************/
int FAR PASCAL PageSizeX(void)
{
return ((PrinterInfo.ptPageSize.x/PrinterInfo.ptResolution.x)*72*20);
}
/*************************************************************************
Exported Draw Line Function, takes it parameters in TWIPS
*************************************************************************/
BOOL FAR PASCAL DrawLine(int nX1, int nY1, int nX2, int nY2)
{
nX1 = MulDiv(nX1, PrinterInfo.ptResolution.x, (72 * 20));
nY1 = MulDiv(nY1, PrinterInfo.ptResolution.y, (72 * 20));
nX2 = MulDiv(nX2, PrinterInfo.ptResolution.x, (72 * 20));
nY2 = MulDiv(nY2, PrinterInfo.ptResolution.y, (72 * 20));
return FDrawLine(ppPrinter.hDC, nX1, nY1, nX2, nY2);
}
/*************************************************************************
Exported Draw Rectangle Function, takes it parameters in TWIPS
*************************************************************************/
BOOL FAR PASCAL DrawRectangle(int nX1, int nY1, int nX2, int nY2)
{
nX1 = MulDiv(nX1, PrinterInfo.ptResolution.x, (72 * 20));
nY1 = MulDiv(nY1, PrinterInfo.ptResolution.y, (72 * 20));
nX2 = MulDiv(nX2, PrinterInfo.ptResolution.x, (72 * 20));
nY2 = MulDiv(nY2, PrinterInfo.ptResolution.y, (72 * 20));
return FDrawRectangle(ppPrinter.hDC, nX1, nY1, nX2, nY2);
}
/*************************************************************************
Exported Draw Rounded Rectangle Function, takes it
parameters in TWIPS
*************************************************************************/
BOOL FAR PASCAL DrawRndRectangle(int nX1, int nY1, int nX2, int nY2, int nX3, int nY3)
{
nX1 = MulDiv(nX1, PrinterInfo.ptResolution.x, (72 * 20));
nY1 = MulDiv(nY1, PrinterInfo.ptResolution.y, (72 * 20));
nX2 = MulDiv(nX2, PrinterInfo.ptResolution.x, (72 * 20));
nY2 = MulDiv(nY2, PrinterInfo.ptResolution.y, (72 * 20));
nX3 = MulDiv(nX3, PrinterInfo.ptResolution.x, (72 * 20));
nY3 = MulDiv(nY3, PrinterInfo.ptResolution.y, (72 * 20));
return FDrawRndRectangle(ppPrinter.hDC, nX1, nY1, nX2, nY2, nX3, nY3);
}
/*************************************************************************
Exported Draw Ellipse Function, takes it parameters in TWIPS
*************************************************************************/
BOOL FAR PASCAL DrawEllipse(int nX1, int nY1, int nX2, int nY2)
{
nX1 = MulDiv(nX1, PrinterInfo.ptResolution.x, (72 * 20));
nY1 = MulDiv(nY1, PrinterInfo.ptResolution.y, (72 * 20));
nX2 = MulDiv(nX2, PrinterInfo.ptResolution.x, (72 * 20));
nY2 = MulDiv(nY2, PrinterInfo.ptResolution.y, (72 * 20));
return FDrawEllipse( ppPrinter.hDC, nX1, nY1, nX2, nY2);
}
/*************************************************************************
Unconditionally moves the current cursor position
in the Y direction, takes its parameters in 100th's
of an inch.
*************************************************************************/
BOOL FAR PASCAL MoveYPos(int nY)
{
PageInfo.ptCurrentPos.y += (int)((nY * PrinterInfo.ptResolution.y)/100);
if(PageInfo.ptCurrentPos.y > (PrinterInfo.ptPageSize.y - PrinterInfo.rcMargins.top - PrinterInfo.rcMargins.bottom))
{
EjectPage(); // Sets current positon too
}
return TRUE;
}
/*************************************************************************
End of VBPRINT.DLL
*************************************************************************/